1. Field of the Invention
The invention relates generally to methods for testing device designs and more particularly to object-oriented programming methods for performing concurrent testing of multiple devices which may have differing designs and differing test requirements.
2. Description of the Relevant Art
Various problems are encountered in the development of integrated circuits (ICs), printed circuit boards and system level devices. As a result of the increasing speed and complexity, as well as the decreasing size of ICs, it is becoming more and more difficult to test and debug the design and operation of these products. (Debugging is the process of finding and eliminating problems, or bugs, in hardware or software.) When a new design is implemented, it must be debugged and tested to ensure that the device operates as expected. The complexity of debugging and testing has grown commensurately with the complexity of the devices themselves. The increased costs and time to debug and test can cause delays which disrupt manufacturing flows and hinder manufacturers"" efforts to bring the products to market.
A great deal of the time required to develop and implement new microprocessor designs is spent on debugging the design. The impact of debugging on the development cycle of a new microprocessor has resulted in the development of faster and more powerful debugging tools. These tools may include features internal to the microprocessor which facilitate debugging, as well as external tools such as logic analyzers and debug/test software.
Microprocessor debug and test systems in the prior art are typically implemented using a personal computer (PC) which is interfaced with the microprocessor under test. The PC is coupled to interface hardware, which is in turn coupled to the microprocessor. Software tools are executed on the PC to provide debug/test functionality. The debug/test setup may also be configured to be used with multiple processors. A multi-processor test system uses essentially the same setup as a uniprocessor test system but, in the multi-processor system, the interface hardware is required to detect signals generated by the debug/test software and determine which of the processors is the intended recipient of each signal. Likewise, the responsive signals produced by each of the processors must be identified to the debug/test software as originating from a particular processor. The interface hardware may therefore be very complex and expensive.
Software debug/test tools may also be very complex. Many individual tests must be conducted on a microprocessor to ensure that the device performs each of its functions properly. The testing of the microprocessor is made more complicated by the fact that there are normally a number of revisions of each processor design. The various revisions may have differences which require that a particular test be performed differently on each revision. Program code which correctly performs the test on one of the revisions of the microprocessor may therefore have to be modified before it can be performed on another of the revisions of the microprocessor. The revised test may use different data, or it may involve the execution of entirely different instructions. The test system should provide the capability to test a first processor of a first revision and then test a processor of a second revision without having to entirely reconfigure the system. A debug/test application must be programmed with the appropriate data and/or test procedures for each of the revisions.
There are several approaches to the problem of testing the different revisions of a microprocessor. The simplest approach is to determine the appropriate test for each feature of a particular revision and code these tests into a debug/test application which is designed specifically for that revision. A separate application is then created for each revision. This approach has several drawbacks: it necessitates a large amount of code; the code for one revision may be duplicative of a substantial portion of the code for another revision; and modifications to a test which is identical in the code for each revision must be made separately to the applications for each of the revisions.
A similar approach entails including all of the test code for each revision in a single application and using preprocessor directives (e.g., #if and #endif) to select portions of the test code to be retained in the compiled application. While this technique would simplify the maintenance of the debug/test code by avoiding duplication of some tests and modifications to those tests, the microprocessor revision must be determined at compile time, so the application must be recompiled each time a different revision is to be tested, or separate executable applications must be maintained for each revision. This approach therefore requires large amounts of resources, either for storage or compiling.
A somewhat less cumbersome approach is to develop a single application which uses branches in the program flow to execute the particular code which is appropriate to each revision of the processor. For each test which varies between the different revisions of the microprocessor, one or more branches are added to the application, each branch containing instructions specific to one of the revisions. When a branch is encountered in the application, the appropriate fork of the branch is selected and the corresponding instructions executed. These branches may be implemented using multiple xe2x80x9cif-thenxe2x80x9d type statements. A pseudocode example illustrating the use of xe2x80x9cif-thenxe2x80x9d statements is shown below.
The increased complexity of the code is illustrated more graphically in FIG. 1. FIG. 1 includes, on the left, a flow diagram of a series of three tests for a single revision and, on the right, a flow diagram of these same tests where one of the tests must be modified for each of three microprocessor revisions. With a single revision, each of the three tests is programmed and executed in a straightforward, sequential fashion. With the three separate test revisions, the test code becomes more complex.
The figure shows a simple series of three tests for a single-revision application as well as a corresponding application in which one of the three tests is replaced with several revision-specific tests. This is accomplished by a series of if-then-else statements which test the revision of the device under test and allow the code to branch to the appropriate revision-specific test. As the number of revisions increases, and as the number of revision-specific tests increases, it is clear that the complexity of the code will also increase.
The branches for the different versions of the test are also implemented in many cases using xe2x80x9cswitchxe2x80x9d statements such as
This method of coding the debug/test software can be very cumbersome. If several revisions must be provided for in a particular test within a debug/test application, the code for that test must be replaced with each of the several code variations corresponding to the several revisions. This replacement must be made for every occurrence of the test in the application. Likewise, if the application must be updated to account for a new revision of the microprocessor, the application programmer must not only write new test code, but must also locate each and every instance in the debug/test application in which one of the new tests may be executed. Each instance must then be individually updated for the new revision.
Because a microprocessor may have many hundreds of functions which must be tested, test variations necessitated by the different microprocessor revisions can cause the test application to become quite large and the complexity of the branch structure may make the application confusing and difficult to maintain. As mentioned above, the size of the application may tax the storage resources of the test system. The application will also be less efficient than a single-revision application as a result of the time which must be spent executing the control instructions that determine which branch will be taken and which test will be executed.
The size and complexity of the debug/test software is made even greater by the need to allow for concurrent testing of multiple processors. Just as the various levels of processor revisions necessitated additional branches in the application code, the concurrent testing of several processors can require additional, unwieldy program branches. The additional branches therefore compound the size and complexity problems found in single-processor debug/test applications.
These and other problems may be solved by various embodiments of an object-oriented method and system for performing tests on several microprocessors wherein the tests are specifically designed for microprocessor revisions which have different testing requirements. The method and system take advantage of software programming techniques involving pure virtual functions, abstract base classes, dynamic binding, inheritance and polymorphism and may result in reduced code size and increased maintainability.
A base class is used to enumerate various attributes of a group of devices and various operations relating to the devices. For each revision or variation of the group of devices which are to be tested, a class is derived from the base class. The derived class may be used to define the enumerated operations of one of the device revisions/variations and may also be used to define or assign values to the attributes for that revision. The derived classes corresponding to different revisions will therefore have identically named functions, but the functions themselves may be different.
In one embodiment, the base class is an abstract base class. That is, the class provides names for the member operations and attributes, but does not define them. It is left to the derived classes to provide definition to the operations (i.e., provide code)and to assign values to the attributes. In another embodiment, the base class not only names the operations and attributes, but also defines one or more of them. In this manner, the base class provides defaults for the derived classes. If one of the derived classes requires an operation or attribute which differs from that of the base class, it can be defined in the derived class. This definition will override the default supplied by the base class.
When one of the devices is tested, its revision or variation is determined and an object is instantiated from the class corresponding to the revision or variation. When a function (e.g., test) related to the device is to be performed, the function is called via a reference to the instantiated object. Likewise, when data relating to the device is needed, the data is referenced via the instantiated object. Because the only data and functions xe2x80x9cknownxe2x80x9d to the object are those defined in the corresponding derived class, and because the derived class defines the revision-specific tests and data, the debug/test application automatically uses the revision-specific data and functions appropriate to that device.